Micron Document
πŸŽ–οΈGitΠ―Ρ€Π°πŸŽ–οΈ

Node / meshtastic / Meshtastic-Android / files / .github / workflows / scheduled-updates.yml

Displaying Raw β€’ Download

.github/workflows/scheduled-updates.yml b2a8377bbb01a5875eba4b12f6f1c7e7d9e60a91 (b2a8377b) Text, 12.73 KB

Tff7b72nameTb4b4b4: Ta5d6ffScheduledTa5d6ff Ta5d6ffUpdatesTa5d6ff Ta5d6ff(Firmware,Ta5d6ff Ta5d6ffHardware,Ta5d6ff Ta5d6ffTranslations)

Tff7b72onTb4b4b4:
Tff7b72scheduleTb4b4b4:
Tb4b4b4- Tff7b72cronTb4b4b4: Ta5d6ff'Ta5d6ff0Te6edf3 Ta5d6ff*/6Te6edf3 Ta5d6ff*Te6edf3 Ta5d6ff*Te6edf3 Ta5d6ff*Ta5d6ff' T8b949e# Run every 6 hours (raised from 4h to absorb the added baseline-profile step)
Tff7b72workflow_dispatchTb4b4b4: T8b949e# Allow manual triggering

Tff7b72jobsTb4b4b4:
Tff7b72update_assetsTb4b4b4:
Tff7b72runs-onTb4b4b4: Ta5d6ffubuntu-24.04
Tff7b72ifTb4b4b4: Ta5d6ffgithub.repositoryTa5d6ff Ta5d6ff==Ta5d6ff Ta5d6ff'meshtastic/Meshtastic-Android'
Tff7b72permissionsTb4b4b4:
Tff7b72contentsTb4b4b4: Ta5d6ffwrite T8b949e# To commit files and push branches
Tff7b72pull-requestsTb4b4b4: Ta5d6ffwrite T8b949e# To create pull requests

Tff7b72stepsTb4b4b4:
Tb4b4b4- Tff7b72nameTb4b4b4: Ta5d6ffCheckoutTa5d6ff Ta5d6ffrepository
Tff7b72usesTb4b4b4: Ta5d6ffactions/checkout@v7.0.0
Tff7b72withTb4b4b4:
Tff7b72tokenTb4b4b4: Ta5d6ff${{Ta5d6ff Ta5d6ffsecrets.CROWDIN_GITHUB_TOKENTa5d6ff Ta5d6ff}}

Tb4b4b4- Tff7b72nameTb4b4b4: Ta5d6ffUpdateTa5d6ff Ta5d6fffirmwareTa5d6ff Ta5d6ffreleasesTa5d6ff Ta5d6fflist
Tff7b72idTb4b4b4: Ta5d6fffirmware
Tff7b72runTb4b4b4: Tb4b4b4|
Tff7b72firmware_file_path="androidApp/src/main/assets/firmware_releases.json"
Tff7b72temp_firmware_file="/tmp/new_firmware_releases.json"

Tff7b72echo "Fetching latest firmware releases..."
Tff7b72http_code=$(curl -s -o "$temp_firmware_file" -w '%{http_code}' https://api.meshtastic.org/github/firmware/list || true)
Tff7b72http_code="${http_code:-0}"

Tff7b72if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
Tff7b72echo "::warning::Firmware API returned HTTP $http_code. Skipping firmware update."
Tff7b72echo "status=error" >> "$GITHUB_OUTPUT"
Tff7b72echo "detail=HTTP $http_code from firmware API" >> "$GITHUB_OUTPUT"
Tff7b72elif ! jq empty "$temp_firmware_file" 2>/dev/null; then
Tff7b72echo "::warning::Firmware API returned invalid JSON data. Skipping firmware update."
Tff7b72echo "status=error" >> "$GITHUB_OUTPUT"
Tff7b72echo "detail=Invalid JSON response from firmware API" >> "$GITHUB_OUTPUT"
Tff7b72else
Tff7b72if [ ! -f "$firmware_file_path" ] || ! jq --sort-keys . "$temp_firmware_file" | diff -q - <(jq --sort-keys . "$firmware_file_path"); then
Tff7b72echo "Changes detected in firmware list or local file missing. Updating $firmware_file_path."
Tff7b72cp "$temp_firmware_file" "$firmware_file_path"
Tff7b72echo "status=updated" >> "$GITHUB_OUTPUT"
Tff7b72else
Tff7b72echo "No changes detected in firmware list."
Tff7b72echo "status=unchanged" >> "$GITHUB_OUTPUT"
Tff7b72fi
Tff7b72fi

Tb4b4b4- Tff7b72nameTb4b4b4: Ta5d6ffUpdateTa5d6ff Ta5d6ffhardwareTa5d6ff Ta5d6fflist
Tff7b72idTb4b4b4: Ta5d6ffhardware
Tff7b72runTb4b4b4: Tb4b4b4|
Tff7b72hardware_file_path="androidApp/src/main/assets/device_hardware.json"
Tff7b72temp_hardware_file="/tmp/new_device_hardware.json"

Tff7b72echo "Fetching latest device hardware data..."
Tff7b72http_code=$(curl -s -o "$temp_hardware_file" -w '%{http_code}' https://api.meshtastic.org/resource/deviceHardware || true)
Tff7b72http_code="${http_code:-0}"

Tff7b72if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
Tff7b72echo "::warning::Hardware API returned HTTP $http_code. Skipping hardware update."
Tff7b72echo "status=error" >> "$GITHUB_OUTPUT"
Tff7b72echo "detail=HTTP $http_code from hardware API" >> "$GITHUB_OUTPUT"
Tff7b72elif ! jq empty "$temp_hardware_file" 2>/dev/null; then
Tff7b72echo "::warning::Hardware API returned invalid JSON data. Skipping hardware update."
Tff7b72echo "status=error" >> "$GITHUB_OUTPUT"
Tff7b72echo "detail=Invalid JSON response from hardware API" >> "$GITHUB_OUTPUT"
Tff7b72else
Tff7b72if [ ! -f "$hardware_file_path" ] || ! jq --sort-keys . "$temp_hardware_file" | diff -q - <(jq --sort-keys . "$hardware_file_path"); then
Tff7b72echo "Changes detected in hardware list or local file missing. Updating $hardware_file_path."
Tff7b72cp "$temp_hardware_file" "$hardware_file_path"
Tff7b72echo "status=updated" >> "$GITHUB_OUTPUT"
Tff7b72else
Tff7b72echo "No changes detected in hardware list."
Tff7b72echo "status=unchanged" >> "$GITHUB_OUTPUT"
Tff7b72fi
Tff7b72fi

Tb4b4b4- Tff7b72nameTb4b4b4: Ta5d6ffSyncTa5d6ff Ta5d6ffwithTa5d6ff Ta5d6ffCrowdin
Tff7b72usesTb4b4b4: Ta5d6ffcrowdin/github-action@v2
Tff7b72withTb4b4b4:
Tff7b72base_urlTb4b4b4: Ta5d6ff'Ta5d6ffhttps://meshtastic.crowdin.com/api/v2Ta5d6ff'
Tff7b72configTb4b4b4: Ta5d6ff'Ta5d6ffcrowdin.ymlTa5d6ff'
Tff7b72crowdin_branch_nameTb4b4b4: Ta5d6ff'Ta5d6ffmainTa5d6ff'
Tff7b72upload_sourcesTb4b4b4: Ta5d6fftrue
Tff7b72upload_sources_argsTb4b4b4: Ta5d6ff'Ta5d6ff--preserve-hierarchyTa5d6ff'
Tff7b72upload_translationsTb4b4b4: Ta5d6fffalse
Tff7b72download_translationsTb4b4b4: Ta5d6fftrue
Tff7b72download_translations_argsTb4b4b4: Ta5d6ff'Ta5d6ff--preserve-hierarchyTa5d6ff'
Tff7b72create_pull_requestTb4b4b4: Ta5d6fffalse
Tff7b72commit_messageTb4b4b4: Ta5d6ff'Ta5d6ffchore(l10n):Te6edf3 Ta5d6ffNewTe6edf3 Ta5d6ffCrowdinTe6edf3 Ta5d6ffTranslationsTe6edf3 Ta5d6fffromTe6edf3 Ta5d6ffscheduledTe6edf3 Ta5d6ffupdateTa5d6ff'
Tff7b72push_translationsTb4b4b4: Ta5d6fffalse
Tff7b72push_sourcesTb4b4b4: Ta5d6fffalse
Tff7b72localization_branch_nameTb4b4b4: Ta5d6ff${{Ta5d6ff Ta5d6ffgithub.ref_nameTa5d6ff Ta5d6ff}}
Tff7b72envTb4b4b4:
Tff7b72GITHUB_TOKENTb4b4b4: Ta5d6ff${{Ta5d6ff Ta5d6ffsecrets.CROWDIN_GITHUB_TOKENTa5d6ff Ta5d6ff}}
Tff7b72CROWDIN_PROJECT_IDTb4b4b4: Ta5d6ff${{Ta5d6ff Ta5d6ffsecrets.CROWDIN_PROJECT_IDTa5d6ff Ta5d6ff}}
Tff7b72CROWDIN_PERSONAL_TOKENTb4b4b4: Ta5d6ff${{Ta5d6ff Ta5d6ffsecrets.CROWDIN_PERSONAL_TOKENTa5d6ff Ta5d6ff}}

Tb4b4b4- Tff7b72nameTb4b4b4: Ta5d6ffFixTa5d6ff Ta5d6fffileTa5d6ff Ta5d6ffpermissions
Tff7b72runTb4b4b4: Ta5d6ffsudoTa5d6ff Ta5d6ffchownTa5d6ff Ta5d6ff-RTa5d6ff Ta5d6ff$USER:$USERTa5d6ff Ta5d6ff.

T8b949e# Early warning for overlength store-listing translations just pulled from
T8b949e# Crowdin. Non-blocking on purpose: a hard failure here would abort the
T8b949e# firmware/hardware/graphs job and stop the PR from being created. The
T8b949e# hard gate is the check-metadata job in pull-request.yml, which runs
T8b949e# against the PR this workflow opens.
Tb4b4b4- Tff7b72nameTb4b4b4: Ta5d6ffCheckTa5d6ff Ta5d6ffstoreTa5d6ff Ta5d6ffmetadataTa5d6ff Ta5d6fflengths
Tff7b72continue-on-errorTb4b4b4: Ta5d6fftrue
Tff7b72runTb4b4b4: Ta5d6ffpython3Ta5d6ff Ta5d6ffscripts/check-metadata-length.py

Tb4b4b4- Tff7b72nameTb4b4b4: Ta5d6ffGradleTa5d6ff Ta5d6ffSetup
Tff7b72usesTb4b4b4: Ta5d6ff./.github/actions/gradle-setup
Tff7b72withTb4b4b4:
Tff7b72gradle_encryption_keyTb4b4b4: Ta5d6ff${{Ta5d6ff Ta5d6ffsecrets.GRADLE_ENCRYPTION_KEYTa5d6ff Ta5d6ff}}
Tff7b72cache_read_onlyTb4b4b4: Ta5d6ff'Ta5d6fffalseTa5d6ff'

Tb4b4b4- Tff7b72nameTb4b4b4: Ta5d6ffUpdateTa5d6ff Ta5d6ffGraphs
Tff7b72runTb4b4b4: Ta5d6ff./gradlewTa5d6ff Ta5d6ffgraphUpdate
Tff7b72continue-on-errorTb4b4b4: Ta5d6fftrue

T8b949e# ── Baseline Profile regeneration ───────────────────────────────────
T8b949e# Runs on every scheduled tick (and manual dispatch). Generation needs a booted emulator
T8b949e# (~10 min); continue-on-error keeps flakiness from blocking the firmware/translation PR.
Tb4b4b4- Tff7b72nameTb4b4b4: Ta5d6ffEnableTa5d6ff Ta5d6ffKVMTa5d6ff Ta5d6ff(forTa5d6ff Ta5d6fftheTa5d6ff Ta5d6ffemulator)
Tff7b72runTb4b4b4: Tb4b4b4|
Tff7b72echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' \
Tff7b72| sudo tee /etc/udev/rules.d/99-kvm4all.rules
Tff7b72sudo udevadm control --reload-rules
Tff7b72sudo udevadm trigger --name-match=kvm

Tb4b4b4- Tff7b72nameTb4b4b4: Ta5d6ffGenerateTa5d6ff Ta5d6ffBaselineTa5d6ff Ta5d6ffProfile
Tff7b72idTb4b4b4: Ta5d6ffgenerate_baseline
Tff7b72continue-on-errorTb4b4b4: Ta5d6fftrue T8b949e# Emulator flakiness must not block the firmware/translation PR.
Tff7b72usesTb4b4b4: Ta5d6ffreactivecircus/android-emulator-runner@v2
Tff7b72withTb4b4b4:
Tff7b72api-levelTb4b4b4: Ta5d6ff34
Tff7b72targetTb4b4b4: Ta5d6ffgoogle_apis T8b949e# google flavor needs GMS (Maps) on the device image
Tff7b72archTb4b4b4: Ta5d6ffx86_64
Tff7b72profileTb4b4b4: Ta5d6ffpixel_6
Tff7b72disable-animationsTb4b4b4: Ta5d6fftrue
Tff7b72emulator-optionsTb4b4b4: Ta5d6ff-no-windowTa5d6ff Ta5d6ff-gpuTa5d6ff Ta5d6ffswiftshader_indirectTa5d6ff Ta5d6ff-noaudioTa5d6ff Ta5d6ff-no-boot-animTa5d6ff Ta5d6ff-camera-backTa5d6ff Ta5d6ffnone
T8b949e# Writes androidApp/src/google/generated/baselineProfiles/ via the androidx.baselineprofile plugin.
T8b949e# --no-configuration-cache: the underlying connectedGoogleNonMinifiedReleaseAndroidTest task is not
T8b949e# config-cache serializable (SeparateTestModuleTestData / ResolutionBackedFileCollection), and the
T8b949e# project enables org.gradle.configuration-cache by default β€” same workaround used in reusable-check.yml.
Tff7b72scriptTb4b4b4: Ta5d6ff./gradlewTa5d6ff Ta5d6ff:androidApp:generateGoogleReleaseBaselineProfileTa5d6ff Ta5d6ff-Pci=trueTa5d6ff Ta5d6ff--no-configuration-cache

Tb4b4b4- Tff7b72nameTb4b4b4: Ta5d6ffDetectTa5d6ff Ta5d6ffbaselineTa5d6ff Ta5d6ffprofileTa5d6ff Ta5d6ffchanges
Tff7b72idTb4b4b4: Ta5d6ffbaseline
Tff7b72runTb4b4b4: Tb4b4b4|
Tff7b72profile_dir="androidApp/src/google/generated/baselineProfiles"
Tff7b72outcome="${{ steps.generate_baseline.outcome }}"
Tff7b72if [ "$outcome" = "skipped" ]; then
Tff7b72echo "status=skipped" >> "$GITHUB_OUTPUT"
Tff7b72elif [ "$outcome" != "success" ]; then
Tff7b72echo "::warning::Baseline profile generation failed (outcome: $outcome). Skipping."
Tff7b72echo "status=error" >> "$GITHUB_OUTPUT"
Tff7b72elif [ -n "$(git status --porcelain "$profile_dir" 2>/dev/null)" ]; then
Tff7b72echo "status=updated" >> "$GITHUB_OUTPUT"
Tff7b72else
Tff7b72echo "status=unchanged" >> "$GITHUB_OUTPUT"
Tff7b72fi

Tb4b4b4- Tff7b72nameTb4b4b4: Ta5d6ffBuildTa5d6ff Ta5d6ffPRTa5d6ff Ta5d6ffbody
Tff7b72idTb4b4b4: Ta5d6ffpr_body
Tff7b72runTb4b4b4: Tb4b4b4|
Tff7b72firmware_status="${{ steps.firmware.outputs.status }}"
Tff7b72firmware_detail="${{ steps.firmware.outputs.detail }}"
Tff7b72hardware_status="${{ steps.hardware.outputs.status }}"
Tff7b72hardware_detail="${{ steps.hardware.outputs.detail }}"
Tff7b72baseline_status="${{ steps.baseline.outputs.status }}"

Tff7b72body="This PR includes automated updates from the scheduled workflow:"
Tff7b72body+=$'\n'

Tff7b72# Firmware status
Tff7b72case "$firmware_status" in
Tff7b72updated) body+=$'\n'"- βœ… \`firmware_releases.json\` updated from the Meshtastic API." ;;
Tff7b72unchanged) body+=$'\n'"- βœ”οΈ \`firmware_releases.json\` checked β€” no changes detected." ;;
Tff7b72error) body+=$'\n'"- ⚠️ \`firmware_releases.json\` skipped β€” ${firmware_detail}." ;;
Tff7b72*) body+=$'\n'"- ❓ \`firmware_releases.json\` β€” unknown status." ;;
Tff7b72esac

Tff7b72# Hardware status
Tff7b72case "$hardware_status" in
Tff7b72updated) body+=$'\n'"- βœ… \`device_hardware.json\` updated from the Meshtastic API." ;;
Tff7b72unchanged) body+=$'\n'"- βœ”οΈ \`device_hardware.json\` checked β€” no changes detected." ;;
Tff7b72error) body+=$'\n'"- ⚠️ \`device_hardware.json\` skipped β€” ${hardware_detail}." ;;
Tff7b72*) body+=$'\n'"- ❓ \`device_hardware.json\` β€” unknown status." ;;
Tff7b72esac

Tff7b72# Baseline profile (daily / manual only)
Tff7b72case "$baseline_status" in
Tff7b72updated) body+=$'\n'"- βœ… \`androidApp\` baseline profile regenerated on an emulator." ;;
Tff7b72unchanged) body+=$'\n'"- βœ”οΈ \`androidApp\` baseline profile regenerated β€” no changes detected." ;;
Tff7b72error) body+=$'\n'"- ⚠️ \`androidApp\` baseline profile generation failed β€” skipped (see workflow logs)." ;;
Tff7b72skipped) ;; # Not a daily/manual run β€” omit the line entirely.
Tff7b72*) ;;
Tff7b72esac

Tff7b72# Crowdin & graphs (always attempted)
Tff7b72body+=$'\n'"- Source strings were uploaded to Crowdin."
Tff7b72body+=$'\n'"- Latest translations were downloaded from Crowdin (if available)."
Tff7b72body+=$'\n'"- Updated module dependency graphs in README.md files (if changed)."
Tff7b72body+=$'\n'
Tff7b72body+=$'\n'"Please review the changes."

Tff7b72# Write multi-line body to output
Tff7b72{
Tff7b72echo "content<<PREOF"
Tff7b72echo "$body"
Tff7b72echo "PREOF"
Tff7b72} >> "$GITHUB_OUTPUT"

Tb4b4b4- Tff7b72nameTb4b4b4: Ta5d6ffCreateTa5d6ff Ta5d6ffPullTa5d6ff Ta5d6ffRequestTa5d6ff Ta5d6ffifTa5d6ff Ta5d6ffchangesTa5d6ff Ta5d6ffoccurred
Tff7b72usesTb4b4b4: Ta5d6ffpeter-evans/create-pull-request@v8
Tff7b72withTb4b4b4:
Tff7b72tokenTb4b4b4: Ta5d6ff${{Ta5d6ff Ta5d6ffsecrets.CROWDIN_GITHUB_TOKENTa5d6ff Ta5d6ff}}
Tff7b72commit-messageTb4b4b4: Tb4b4b4|
Tff7b72chore: Scheduled updates (Firmware, Hardware, Translations, Graphs, Baseline)

Tff7b72Automated updates for:
Tff7b72- Firmware releases list
Tff7b72- Device hardware list
Tff7b72- Crowdin source string uploads
Tff7b72- Crowdin translation downloads
Tff7b72- Module dependency graphs
Tff7b72- androidApp baseline profile
Tff7b72titleTb4b4b4: Ta5d6ff'Ta5d6ffchore:Te6edf3 Ta5d6ffScheduledTe6edf3 Ta5d6ffupdatesTe6edf3 Ta5d6ff(Firmware,Te6edf3 Ta5d6ffHardware,Te6edf3 Ta5d6ffTranslations,Te6edf3 Ta5d6ffGraphs,Te6edf3 Ta5d6ffBaseline)Ta5d6ff'
Tff7b72bodyTb4b4b4: Ta5d6ff${{Ta5d6ff Ta5d6ffsteps.pr_body.outputs.contentTa5d6ff Ta5d6ff}}
Tff7b72branchTb4b4b4: Ta5d6ff'Ta5d6ffscheduled-updatesTa5d6ff'
Tff7b72baseTb4b4b4: Ta5d6ff'Ta5d6ffmainTa5d6ff'
Tff7b72delete-branchTb4b4b4: Ta5d6fftrue
T8b949e# Only stage the baseline-profile dir when generation actually produced changes. When the emulator
T8b949e# boots far enough for Gradle to create an *empty* baselineProfiles/ dir but generation then fails,
T8b949e# `git add <glob>` aborts with "pathspec did not match any files", which would hard-fail this step
T8b949e# and defeat the continue-on-error on the generation step above.
Tff7b72add-pathsTb4b4b4: Tb4b4b4|
Tff7b72androidApp/src/main/assets/firmware_releases.json
Tff7b72androidApp/src/main/assets/device_hardware.json
Tff7b72${{ steps.baseline.outputs.status == 'updated' && 'androidApp/src/google/generated/baselineProfiles/**' || '' }}
Tff7b72fastlane/metadata/android/**
Tff7b72**/strings.xml
Tff7b72**/README.md
Tff7b72docs/**/*.md
Tff7b72labelsTb4b4b4: Tb4b4b4|
Tff7b72automation
Tff7b72l10n
Tff7b72firmware
Tff7b72hardware

Tff7b72check-workflow-statusTb4b4b4:
Tff7b72nameTb4b4b4: Ta5d6ffCheckTa5d6ff Ta5d6ffWorkflowTa5d6ff Ta5d6ffStatus
Tff7b72runs-onTb4b4b4: Ta5d6ffubuntu-24.04-arm
Tff7b72permissionsTb4b4b4: Tb4b4b4{Tb4b4b4}
Tff7b72needsTb4b4b4:
Tb4b4b4- Ta5d6ffupdate_assets
Tff7b72ifTb4b4b4: Ta5d6ffalways()
Tff7b72stepsTb4b4b4:
Tb4b4b4- Tff7b72nameTb4b4b4: Ta5d6ffCheckTa5d6ff Ta5d6ffWorkflowTa5d6ff Ta5d6ffStatus
Tff7b72ifTb4b4b4: Ta5d6ff"Ta5d6ffcontains(needs.*.result,Te6edf3 Ta5d6ff'failure')Te6edf3 Ta5d6ff||Te6edf3 Ta5d6ffcontains(needs.*.result,Te6edf3 Ta5d6ff'cancelled')Ta5d6ff"
Tff7b72runTb4b4b4: Tb4b4b4|
Tff7b72echo "One of the dependent jobs failed or was cancelled. Failing the workflow."
Tff7b72exit 1

Served by rngit 1.5.2 - Generated in 0.07s